package com.jiangyg.mall.authz;

import com.jiangyg.mall.authz.constant.AuthzConstant;
import com.jiangyg.mall.core.utils.Assert;
import com.jiangyg.mall.core.utils.JsonUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import static com.jiangyg.mall.authz.constant.MsgConstant.AUTHZ_REQUEST_NOTFOUND_AUTHINFO;
import static com.jiangyg.mall.authz.constant.MsgConstant.AUTHZ_REQUEST_PARSE_ERROR_AUTHINFO;

/**
 * 类描述：会员用户信息上下文
 * <p>注意：此类在 controller 层使用，依赖 request 获取认证信息</p>
 *
 * @author jiangyg
 * @version 4.0
 * @date 2022-10-09
 */
public class MemberInfoHolder {

    /**
     * 会员信息上下文
     */
    private static final ThreadLocal<MemberInfo> contextHolder = new InheritableThreadLocal<>();

    /**
     * 功能描述：清理当前线程上下文
     */
    public static void clearContext() {
        contextHolder.remove();
    }

    /**
     * 功能描述：获取当前线程上下文
     */
    private static MemberInfo currentLoginUserInfo() {
        // 1. 尝试从上下文中获取用户信息
        MemberInfo memberInfo = contextHolder.get();
        if (memberInfo != null) {
            return memberInfo;
        }
        // 2. 尝试从请求中获取用户信息
        final ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Assert.notNull(attributes);
        final HttpServletRequest request = attributes.getRequest();
        Assert.notNull(request);
        final String userInfoBase64String = request.getHeader(AuthzConstant.AUTH_USER_INFO);
        if (StringUtils.isBlank(userInfoBase64String)) {
            throw new NotFoundAuthInfoException(AUTHZ_REQUEST_NOTFOUND_AUTHINFO);
        }
        // 3. 解析用户信息
        try {
            final String userInfoString = new String(Base64.decodeBase64(userInfoBase64String));
            memberInfo = JsonUtils.parseObject(userInfoString, MemberInfo.class);
        } catch (Exception ex) {
            throw new NotFoundAuthInfoException(AUTHZ_REQUEST_PARSE_ERROR_AUTHINFO, ex);
        }
        // 4. 用户信息设置到上下文中
        contextHolder.set(memberInfo);
        return memberInfo;
    }

    /**
     * 功能描述：会员名称
     *
     * @return 用户ID
     */
    public static Long loginMemberId() {
        return Long.parseLong(currentLoginUserInfo().getId());
    }

    /**
     * 功能描述：获取当前登录会员信息
     *
     * @return 当前登录会员信息
     */
    public static MemberInfo loginMemberInfo() {
        return currentLoginUserInfo();
    }

}
